package tuik

import (
	"github.com/nsf/termbox-go"
)

type Kind struct {
	X            int
	Y            int
	Width        int
	Height       int
	Border       []int
	Title        string
	TitleColor   Attr
	Content      string
	ContentColor Attr
	List         []string
	ColorList    []ColorMsg
	ListWay      string
	MouseRoll    bool
	Fg           Attr
	Bg           Attr
}
type ColorMsg struct {
	Msg   string
	Color Attr
}

func Label(k Kind) {
	for _, c := range k.Content {
		termbox.SetCell(k.X, k.Y, c, SetAttr(k.Fg), SetAttr(k.Bg))
		clen := len(string(c))
		if clen == 3 {
			k.X = k.X + 2
		} else {
			k.X++
		}
	}
}

func Slips(k Kind) {
	for _, c := range k.Content {
		termbox.SetCell(k.X, k.Y, c, SetAttr(k.Fg), SetAttr(k.Bg))
		k.Y++
	}
}

func (this Kind) Block(k Kind) {
	u := compareKind(this, k)
	var totext rune
	var fgColor = u.Fg
	var bgColor = u.Bg
	for y := u.Y; y <= (u.Y + u.Height); y++ {
		for x := u.X; x <= (u.X + u.Width); x++ {
			if y == u.Y && x == u.X {
				if u.Border[0] == 0 && u.Border[3] == 0 {
					totext = ' '
					bgColor = u.TitleColor
				} else if u.Border[0] == 1 && u.Border[3] == 0 {
					totext = '─'
					bgColor = u.Bg
				} else if u.Border[0] == 0 && u.Border[3] == 1 {
					totext = '│'
					bgColor = u.Bg
				} else {
					totext = '┌'
					bgColor = u.Bg
				}
			} else if y == u.Y+u.Height && x == u.X {
				if u.Border[2] == 0 && u.Border[3] == 0 {
					totext = ' '
					bgColor = u.Bg
				} else if u.Border[2] == 1 && u.Border[3] == 0 {
					totext = '─'
					bgColor = u.Bg
				} else if u.Border[2] == 0 && u.Border[3] == 1 {
					totext = '│'
					bgColor = u.Bg
				} else {
					totext = '└'
					bgColor = u.Bg
				}
			} else if x == u.X+u.Width && y == u.Y {
				if u.Border[0] == 0 && u.Border[1] == 0 {
					totext = ' '
					bgColor = u.TitleColor
				} else if u.Border[0] == 1 && u.Border[1] == 0 {
					totext = '─'
					bgColor = u.Bg
				} else if u.Border[0] == 0 && u.Border[1] == 1 {
					totext = '│'
					bgColor = u.Bg
				} else {
					totext = '┐'
					bgColor = u.Bg
				}
			} else if x == u.X+u.Width && y == u.Y+u.Height {
				if u.Border[1] == 0 && u.Border[2] == 0 {
					totext = ' '
					bgColor = u.Bg
				} else if u.Border[1] == 0 && u.Border[2] == 1 {
					totext = '─'
					bgColor = u.Bg
				} else if u.Border[1] == 1 && u.Border[2] == 0 {
					totext = '│'
					bgColor = u.Bg
				} else {
					totext = '┘'
					bgColor = u.Bg
				}
			} else if y == u.Y && x > u.X && x < u.X+u.Width {
				if u.Border[0] == 0 {
					totext = ' '
					bgColor = u.TitleColor
				} else {
					totext = '─'
					bgColor = u.Bg
				}
			} else if y == u.Y+u.Height && x > u.X && x < u.X+u.Width {
				if u.Border[2] == 0 {
					totext = ' '
					bgColor = u.Bg
				} else {
					totext = '─'
					bgColor = u.Bg
				}
			} else if x == u.X && y > u.Y && y < u.Y+u.Height {
				if u.Border[3] == 0 {
					totext = ' '
					bgColor = u.Bg
				} else {
					totext = '│'
					bgColor = u.Bg
				}
			} else if x == u.X+u.Width && y > u.Y && y < u.Y+u.Height {
				if u.Border[1] == 0 {
					totext = ' '
					bgColor = u.Bg
				} else {
					totext = '│'
					bgColor = u.Bg
				}
			} else {
				totext = ' '
			}
			termbox.SetCell(x, y, totext, SetAttr(fgColor), SetAttr(bgColor))
		}
	}
	//Title
	if len(u.Title) > 0 {
		if u.TitleColor > 0 {
			if u.Border[0] == 0 {
				Label(Kind{
					X:       u.X + 1,
					Y:       u.Y,
					Fg:      u.Fg,
					Bg:      u.TitleColor,
					Content: u.Title,
				})
			} else {
				Label(Kind{
					X:       u.X + 1,
					Y:       u.Y,
					Fg:      u.TitleColor,
					Bg:      u.Bg,
					Content: u.Title,
				})
			}
		} else {
			Label(Kind{
				X:       u.X + 1,
				Y:       u.Y,
				Fg:      u.Fg,
				Bg:      u.Bg,
				Content: u.Title,
			})

		}
	}
	//List
	var startDot int
	if len(u.List) > 0 {
		listShow := make([]string, u.Height-1)
		if len(u.ListWay) > 0 {
			if u.ListWay == "top" {
				if len(u.List) > len(listShow) {
					startDot = len(u.List) - len(listShow)
					Label(Kind{
						X:       u.X + u.Width,
						Y:       u.Y + 1,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "^",
					})

				} else {
					startDot = 0
				}
				copy(listShow, u.List[startDot:])
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      u.ContentColor,
						Bg:      u.Bg,
						Content: v,
					})
					listY++
				}

			} else if u.ListWay == "down" {
				if len(u.List) > len(listShow) {
					startDot = len(u.List) - len(listShow)
					Label(Kind{
						X:       u.X + u.Width,
						Y:       u.Y + u.Height - 1,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "v",
					})

				} else {
					startDot = 0
				}
				copy(listShow, u.List[startDot:])
				for i, j := 0, len(listShow)-1; i < j; i, j = i+1, j-1 {
					listShow[i], listShow[j] = listShow[j], listShow[i]
				}
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      u.ContentColor,
						Bg:      u.Bg,
						Content: v,
					})
					listY++
				}
			} else if u.ListWay == "left" {
				landShow := make([]string, u.Width-2)
				if len(u.List) > len(landShow) {
					startDot = len(u.List) - len(landShow)
					Label(Kind{
						X:       u.X + 1,
						Y:       u.Y + u.Height,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "<",
					})

				} else {
					startDot = 0
				}
				copy(landShow, u.List[startDot:])
				listX := u.X + 1
				for _, v := range landShow {
					Slips(Kind{
						X:       listX,
						Y:       u.Y + 1,
						Fg:      u.ContentColor,
						Bg:      u.Bg,
						Content: v,
					})
					listX++
				}
			} else if u.ListWay == "right" {
				landShow := make([]string, u.Width-2)
				if len(u.List) > len(landShow) {
					startDot = len(u.List) - len(landShow)
					Label(Kind{
						X:       u.X + u.Width - 1,
						Y:       u.Y + u.Height,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: ">",
					})

				} else {
					startDot = 0
				}
				copy(landShow, u.List[startDot:])
				for i, j := 0, len(landShow)-1; i < j; i, j = i+1, j-1 {
					landShow[i], landShow[j] = landShow[j], landShow[i]
				}

				listX := u.X + 1
				for _, v := range landShow {
					Slips(Kind{
						X:       listX,
						Y:       u.Y + 1,
						Fg:      u.ContentColor,
						Bg:      u.Bg,
						Content: v,
					})
					listX++
				}

			} else {
				copy(listShow, u.List)
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      u.ContentColor,
						Bg:      u.Bg,
						Content: v,
					})
					listY++
				}
			}
		} else {
			copy(listShow, u.List)
			listY := u.Y + 1
			for _, v := range listShow {
				Label(Kind{
					X:       u.X + 1,
					Y:       listY,
					Fg:      u.ContentColor,
					Bg:      u.Bg,
					Content: v,
				})
				listY++
			}
		}

	} else if len(u.ColorList) > 0 {
		listShow := make([]ColorMsg, u.Height-1)
		if len(u.ListWay) > 0 {
			if u.ListWay == "top" {
				if len(u.ColorList) > len(listShow) {
					startDot = len(u.ColorList) - len(listShow)
					Label(Kind{
						X:       u.X + u.Width,
						Y:       u.Y + 1,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "^",
					})

				} else {
					startDot = 0
				}
				copy(listShow, u.ColorList[startDot:])
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      v.Color,
						Bg:      u.Bg,
						Content: v.Msg,
					})
					listY++
				}

			} else if u.ListWay == "down" {
				if len(u.ColorList) > len(listShow) {
					startDot = len(u.ColorList) - len(listShow)
					Label(Kind{
						X:       u.X + u.Width,
						Y:       u.Y + u.Height - 1,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "v",
					})

				} else {
					startDot = 0
				}
				copy(listShow, u.ColorList[startDot:])
				for i, j := 0, len(listShow)-1; i < j; i, j = i+1, j-1 {
					listShow[i], listShow[j] = listShow[j], listShow[i]
				}
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      v.Color,
						Bg:      u.Bg,
						Content: v.Msg,
					})
					listY++
				}
			} else if u.ListWay == "left" {
				landShow := make([]ColorMsg, u.Width-2)
				if len(u.ColorList) > len(landShow) {
					startDot = len(u.ColorList) - len(landShow)
					Label(Kind{
						X:       u.X + 1,
						Y:       u.Y + u.Height,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: "<",
					})

				} else {
					startDot = 0
				}
				copy(landShow, u.ColorList[startDot:])
				listX := u.X + 1
				for _, v := range landShow {
					Slips(Kind{
						X:       listX,
						Y:       u.Y + 1,
						Fg:      v.Color,
						Bg:      u.Bg,
						Content: v.Msg,
					})
					listX++
				}
			} else if u.ListWay == "right" {
				landShow := make([]ColorMsg, u.Width-2)
				if len(u.ColorList) > len(landShow) {
					startDot = len(u.ColorList) - len(landShow)
					Label(Kind{
						X:       u.X + u.Width - 1,
						Y:       u.Y + u.Height,
						Fg:      u.Fg,
						Bg:      u.Bg,
						Content: ">",
					})

				} else {
					startDot = 0
				}
				copy(landShow, u.ColorList[startDot:])
				for i, j := 0, len(landShow)-1; i < j; i, j = i+1, j-1 {
					landShow[i], landShow[j] = landShow[j], landShow[i]
				}

				listX := u.X + 1
				for _, v := range landShow {
					Slips(Kind{
						X:       listX,
						Y:       u.Y + 1,
						Fg:      v.Color,
						Bg:      u.Bg,
						Content: v.Msg,
					})
					listX++
				}

			} else {
				copy(listShow, u.ColorList)
				listY := u.Y + 1
				for _, v := range listShow {
					Label(Kind{
						X:       u.X + 1,
						Y:       listY,
						Fg:      v.Color,
						Bg:      u.Bg,
						Content: v.Msg,
					})
					listY++
				}
			}
		} else {
			copy(listShow, u.ColorList)
			listY := u.Y + 1
			for _, v := range listShow {
				Label(Kind{
					X:       u.X + 1,
					Y:       listY,
					Fg:      v.Color,
					Bg:      u.Bg,
					Content: v.Msg,
				})
				listY++
			}
		}
	}
}

func compareKind(this Kind, k Kind) Kind {
	u := Kind{}
	if k.X > 0 {
		u.X = k.X
	} else {
		u.X = this.X
	}
	if k.Y > 0 {
		u.Y = k.Y
	} else {
		u.Y = this.Y
	}
	if k.Width > 0 {
		u.Width = k.Width
	} else {
		u.Width = this.Width
	}
	if k.Height > 0 {
		u.Height = k.Height
	} else {
		u.Height = this.Height
	}
	if len(k.Border) > 0 {
		u.Border = k.Border
	} else {
		u.Border = this.Border
	}
	if len(k.Title) > 0 {
		u.Title = k.Title
	} else {
		u.Title = this.Title
	}
	if k.TitleColor > 0 {
		u.TitleColor = k.TitleColor
	} else {
		u.TitleColor = this.TitleColor
	}
	if len(k.Content) > 0 {
		u.Content = k.Content
	} else {
		u.Content = this.Content
	}
	if k.ContentColor > 0 {
		u.ContentColor = k.ContentColor
	} else {
		u.ContentColor = this.ContentColor
	}

	if len(k.List) > 0 {
		u.List = k.List
	} else {
		u.List = this.List
	}
	if len(k.ColorList) > 0 {
		u.ColorList = k.ColorList
	} else {
		u.ColorList = this.ColorList
	}

	if len(k.ListWay) > 0 {
		u.ListWay = k.ListWay
	} else {
		u.ListWay = this.ListWay
	}

	if k.Fg > 0 {
		u.Fg = k.Fg
	} else {
		u.Fg = this.Fg
	}
	if k.Bg > 0 {
		u.Bg = k.Bg
	} else {
		u.Bg = this.Bg
	}
	return u
}
func Flush() {
	termbox.Flush()
}
func Sync() {
	termbox.Sync()
}
func Size() (w int, h int) {
	w, h = termbox.Size()
	return w, h
}
func Init() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}
	termbox.SetOutputMode(termbox.Output256)
}
func Close() {
	termbox.Close()
}
